<template>
    <div class="blog-toc-container">
        <h2>目录</h2>
        <RightList :list="tocWithSelect" @select="handleSelect" />
    </div>
</template>

<script>
import RightList from "./RightList.vue"
import {debounce} from '@/utils'
export default {
    components: { RightList },
    props: {
        toc: {
            type: Array,
            require: true
        }
    },
    data() {
        return {
            activeAnchor: ""
        }
    },
    created() {
        this.setSelectDebounce = debounce(this.setSelect,50)
        this.$bus.$on("mainScroll",this.setSelectDebounce);
    },
    destroyed(){  
        this.$bus.$off("mainScroll",this.setSelectDebounce);
    },
    methods: {
        handleSelect(item) {
            location.hash = item.anchor;
        },
        //设置activeAnchor为正确的值
        setSelect(scrollDom) {
            if(!scrollDom){
                return;
            }
            this.activeAnchor = "";
            const range = 50;
            for (const dom of this.doms) {
                if (!dom) {
                    continue;
                }
                //得到元素离视口顶部的距离
                const top = dom.getBoundingClientRect().top
                if (top >= 0 && top <= range) {
                    //在规定的范围内
                    this.activeAnchor = dom.id;
                    return;
                } else if (top > range) {
                    //在规定的范围下方
                    return;
                } else {
                    // 在规定的范围上方
                    this.activeAnchor = dom.id;
                }
            }
        }
    },
    computed: {
        //根据toc属性得到带有数组的toc数组
        tocWithSelect() {
            const getTOC = (toc = []) => {
                return toc.map(t => ({
                    ...t,
                    isSelect: t.anchor === this.activeAnchor,
                    children: getTOC(t.children)
                }))
            };
            return getTOC(this.toc)
        },
        // 根据toc得到他们对应的元素数组
        doms() {
            const doms = [];
            const addToDoms = toc => {
                for (const t of toc) {
                    doms.push(document.getElementById(t.anchor));
                    if (t.children && t.children.length) {
                        addToDoms(t.children);
                    }
                }
            };
            addToDoms(this.toc);
            return doms;
        }
    }
}
</script>

<style scoped lang="less">
.blog-toc-container {
    width: 300px;
    box-sizing: border-box;
    padding: 20px;

    h2 {
        font-weight: bold;
        letter-spacing: 2px;
        font-size: 1em;
        margin: 0;
    }
}
</style>